/*
 * TraceOperand.c
 *	Define processes about LinkOperand
 *  Created on: 2012/08/08
 *      Author: guanxiaoying
 */

#include "../tracedef.h"
#include "trace_cmd.h"
#include "../../table/core_table.h"

/* skip ASM_CMD_GETOPERAND commands */
static AST tr_OpeSkipGetOperand( AST astOperand ){
	AST astCmdList;
	if( LinkOperand.isCommandList(astOperand) ){
		astCmdList = LinkOperand.getParameter( astOperand );
		if( ASM_CMD_GETOPERAND == stCmdListAccess.opKind.get( astCmdList ) ){
			astOperand = LinkCommandList.getLeftOperand( astCmdList );
			return tr_OpeSkipGetOperand( astOperand );
		}
	}
	return astOperand;
}
/* Get the LinkConstant if the LinkOperand is a constant */
AST Tr_OpeGetConstant( AST astOperand ){
	AST astCmd;
	astOperand = tr_OpeSkipGetOperand(astOperand);
	if( LinkOperand.isConstant(astOperand) ){
		astCmd = LinkOperand.getParameter( astOperand );
		return astCmd;
	}
	return 0;
}
/* whether the LinkOperand is a constant */
BOOL Tr_OpeIsConstant( AST astOperand ){
	return Tr_OpeGetConstant( astOperand ) > 0;
}
/* Get the LinkStrings if the LinkOperand is a string */
AST Tr_OpeGetString( AST astOperand ){
	AST astCmd;
	astOperand = tr_OpeSkipGetOperand(astOperand);
	if( LinkOperand.isConstString(astOperand) ){
		astCmd = LinkOperand.getParameter( astOperand );
		return astCmd;
	}
	return 0;
}
/* whether the LinkOperand is a string */
BOOL Tr_OpeIsString( AST astOperand ){
	return Tr_OpeGetString( astOperand ) > 0;
}
/* Get the LinkCommandList if the LinkOperand is a LinkCommandList */
AST Tr_OpeGetCommand( AST astOperand ){
	AST astCmd;
	if( LinkOperand.isCommandList(astOperand) ){
		astCmd = LinkOperand.getParameter( astOperand );
		return astCmd;
	}
	return 0;
}
/* whether the LinkOperand is a LinkCommandList */
BOOL Tr_OpeIsCommand( AST astOperand ){
	return Tr_OpeGetCommand( astOperand ) > 0;
}
/* Get the LinkFunction if the LinkOperand is a LinkFunction */
AST Tr_OpeGetFunction( AST astOperand ){
	AST astFunc;
	astOperand = tr_OpeSkipGetOperand(astOperand);
	if( LinkOperand.isFunction(astOperand) ){
		astFunc = LinkOperand.getParameter( astOperand );
		return astFunc;
	}
	return 0;
}
/* whether the LinkOperand is a LinkFunction */
BOOL Tr_OpeIsFunction( AST astOperand ){
	return Tr_OpeGetFunction( astOperand ) > 0;
}
/* Get the LinkVariable if the LinkOperand is a LinkVariable */
AST Tr_OpeGetVari( AST astOperand ){
	AST astVari;
	astOperand = tr_OpeSkipGetOperand(astOperand);
	if( LinkOperand.isVariable(astOperand) ){
		astVari = LinkOperand.getParameter( astOperand );
		return astVari;
	}
	return 0;
}
/* whether the LinkOperand is a LinkVariable */
BOOL Tr_OpeIsVari( AST astOperand ){
	return Tr_OpeGetVari( astOperand ) > 0 ;
}
/* Get the LinkVariable if the LinkOperand is a global variable */
AST Tr_OpeGetGblVari( AST astOperand ){
	AST astVari;
	astOperand = tr_OpeSkipGetOperand(astOperand);
	if( LinkOperand.isVariable(astOperand) ){
		astVari = LinkOperand.getParameter( astOperand );
		if( astVari > 0 ){
			if( LinkVariable.getLinkage( astVari ) > 0 ){
				return astVari;
			}
		}
	}
	return 0;
}
/* whether the LinkOperand is a global variable */
BOOL Tr_OpeIsGblVari( AST astOperand ){
	return Tr_OpeGetGblVari( astOperand ) > 0;
}
/* Get the LinkVariable if the LinkOperand is a temporary variable */
AST Tr_OpeGetTempVari( AST astOperand ){
	AST astVari;
	astOperand = tr_OpeSkipGetOperand(astOperand);
	if( LinkOperand.isVariable(astOperand) ){
		astVari = LinkOperand.getParameter( astOperand );
		if( astVari > 0 ){
			if( LinkVariable.getLinkage( astVari ) == 0 ){
				if( !LinkVariable.isStatic( astVari ) && !LinkVariable.isExtern( astVari ) ){
					return astVari;
				}
			}
		}
	}
	return 0;
}
/* whether the LinkOperand is a temporary variable */
BOOL Tr_OpeIsTempVari( AST astOperand ){
	return Tr_OpeGetTempVari( astOperand ) > 0;
}
/* get the trace-variable from LinkOperand if it's a temporary variable */
AST Tr_OpeGetTraceVari( AST astOperand ){
	AST astVari;
	astVari = Tr_OpeGetTempVari( astOperand );
	if( astVari > 0 ){
		return Tr_VarBlkGetVariOrAdd( astVari, Tr_PathParamGetCurrVariBlock() );
	}
	return 0;
}
